package com.zkthink.ceres.promotion.service.impl;

import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.zkthink.base.R;
import com.zkthink.cache.repository.RedisRepositoryImpl;
import com.zkthink.ceres.promotion.constants.PromotionConstant;
import com.zkthink.ceres.promotion.dao.CouponMapper;
import com.zkthink.ceres.promotion.dao.MemberCouponMapper;
import com.zkthink.ceres.promotion.dao.PromotionMapper;
import com.zkthink.ceres.promotion.entity.Coupon;
import com.zkthink.ceres.promotion.entity.MemberCoupon;
import com.zkthink.ceres.promotion.entity.Promotion;
import com.zkthink.ceres.promotion.enums.PromotionTypeEnum;
import com.zkthink.ceres.promotion.service.PromotionService;
import com.zkthink.base.service.SuperServiceImpl;

import com.zkthink.ceres.promotion.vo.web.CouponVO;
import com.zkthink.ceres.promotion.vo.web.PromotionShowVO;
import com.zkthink.ceres.promotion.vo.web.PromotionVO;
import com.zkthink.database.mybatis.conditions.Wraps;
import com.zkthink.dozer.DozerUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 营销活动表
 * </p>
 *
 * @author kellen
 * @date 2020-06-16
 */
@Slf4j
@AllArgsConstructor
@Service
public class PromotionServiceImpl extends SuperServiceImpl<PromotionMapper, Promotion> implements PromotionService {

    private RedisRepositoryImpl redisRepository;

    private CouponMapper couponMapper;

    private DozerUtils dozerUtils;

    private MemberCouponMapper memberCouponMapper;

    @Override
    public List<PromotionShowVO> findPromotionListByProductId(Long productId) {
        if(productId==null){
            return Collections.emptyList();
        }
        List<PromotionShowVO> resultList = new ArrayList<PromotionShowVO>();
        String key = PromotionConstant.PRODUCT_PROMOTION_RELATION_PREFIX + productId;
        Set<Object> promotionSet = redisRepository.getRedisTemplate().opsForZSet().range(key,0,-1);
        if(promotionSet!=null && promotionSet.size()>0){
            for(Object promotionId:promotionSet){
                PromotionShowVO promotionShowVO = new PromotionShowVO();
                Long proId = Long.valueOf(promotionId.toString());
                promotionShowVO.setId(proId);

                Promotion promotion = JSON.parseObject(redisRepository.get(PromotionConstant.PROMOTION_PREFIX + proId),Promotion.class);
                if(promotion!=null){
                    promotionShowVO.setTag(promotion.getTag());
                }
                resultList.add(promotionShowVO);
            }
        }
        return resultList;
    }

    @Override
    public R<List<PromotionVO>> findPromotionList(Long mid, String promotionIds) {
        if(StringUtils.isBlank(promotionIds)){
            R.success(new ArrayList<>());
        }
        List<String> promotionIdList = ListUtil.toList(promotionIds.split(","));
        List<PromotionVO> promotionVOList = new ArrayList<PromotionVO>();
        for(String promotionId:promotionIdList){
            String key = PromotionConstant.PROMOTION_PREFIX + promotionId;
            String promotionStr = (String)redisRepository.get(key);
            if(StringUtils.isNoneBlank(promotionStr)){
                Promotion promotion = JSON.parseObject(promotionStr,Promotion.class);
                PromotionVO promotionVO = dozerUtils.map(promotion, PromotionVO.class);
                promotionVOList.add(promotionVO);
                if(promotion.getPromotionType() == PromotionTypeEnum.DISCOUNT_COUPON.getCode()){
                    List<Coupon> couponList = couponMapper.selectList(Wraps.<Coupon>lbQ().eq(Coupon::getBizId,promotion.getId()).eq(Coupon::getIsDelete,0));
                    List<CouponVO> couponVOList = dozerUtils.mapList(couponList, CouponVO.class);

                    promotionVO.setCouponVOList(couponVOList);

                    if(mid!=null && mid!=0){
                        List<Long> couponIdList = couponVOList.stream().map(Coupon::getId).collect(Collectors.toList());
                        List<MemberCoupon> memberCouponList = memberCouponMapper.selectList(Wraps.<MemberCoupon>lbQ()
                                                        .eq(MemberCoupon::getMid,mid).in(MemberCoupon::getCouponId,couponIdList)
                                                        .eq(MemberCoupon::getIsDeleted,0));
                        Map<Long,Integer> receiveMap = new HashMap<Long,Integer>();
                        for(MemberCoupon memberCoupon:memberCouponList){
                            receiveMap.put(memberCoupon.getCouponId(),1);
                        }
                        for(CouponVO couponVo:couponVOList){
                            couponVo.setReceived(receiveMap.getOrDefault(couponVo.getId(),0));
                        }
                    }
                }
            }
        }
        return R.success(promotionVOList);
    }

    @Override
    public Map<Long,List<PromotionVO>> findPromotionDetail(Long mid, Set<Long> productIdList) {
        if(CollectionUtils.isEmpty(productIdList)){
            R.success(new ArrayList<>());
        }
        Map<Long,List<PromotionVO>> productPromotionMap = new HashMap<Long,List<PromotionVO>>();
        Map<String,PromotionVO> promotionIdMap = new HashMap<String,PromotionVO>();
        for(Long productId:productIdList){
            //先初始化map
            productPromotionMap.put(productId,new ArrayList<PromotionVO>());

            String key = PromotionConstant.PRODUCT_PROMOTION_RELATION_PREFIX + productId;
            Set<Object> promotionIdSet = redisRepository.getRedisTemplate().opsForZSet().range(key,0,-1);
            if(promotionIdSet!=null){
                for(Object promotionIdObj:promotionIdSet){
                    String promotionIdStr = promotionIdObj.toString();
                    if(promotionIdMap.get(promotionIdStr)==null) {
                        String promotionKey = PromotionConstant.PROMOTION_PREFIX + promotionIdStr;
                        String promotionStr = (String) redisRepository.get(promotionKey);
                        if (StringUtils.isNoneBlank(promotionStr)) {
                            Promotion promotion = JSON.parseObject(promotionStr, Promotion.class);
                            PromotionVO promotionVO = dozerUtils.map(promotion, PromotionVO.class);
                            productPromotionMap.get(productId).add(promotionVO);
                            if (promotion.getPromotionType() == PromotionTypeEnum.DISCOUNT_COUPON.getCode()) {
                                List<Coupon> couponList = couponMapper.selectList(Wraps.<Coupon>lbQ().eq(Coupon::getBizId, promotion.getId()).eq(Coupon::getIsDelete, 0));
                                List<CouponVO> couponVOList = dozerUtils.mapList(couponList, CouponVO.class);

                                promotionVO.setCouponVOList(couponVOList);

                                if (mid != null && mid != 0) {
                                    List<Long> couponIdList = couponVOList.stream().map(Coupon::getId).collect(Collectors.toList());
                                    List<MemberCoupon> memberCouponList = memberCouponMapper.selectList(Wraps.<MemberCoupon>lbQ()
                                            .eq(MemberCoupon::getMid, mid).in(MemberCoupon::getCouponId, couponIdList)
                                            .eq(MemberCoupon::getIsDeleted, 0));
                                    Map<Long, Integer> receiveMap = new HashMap<Long, Integer>();
                                    for (MemberCoupon memberCoupon : memberCouponList) {
                                        receiveMap.put(memberCoupon.getCouponId(), 1);
                                    }
                                    for (CouponVO couponVo : couponVOList) {
                                        couponVo.setReceived(receiveMap.getOrDefault(couponVo.getId(), 0));
                                    }
                                }
                                promotionIdMap.put(promotionIdStr,promotionVO);
                            }
                        }
                    }else{
                        productPromotionMap.get(productId).add(promotionIdMap.get(promotionIdStr));
                    }
                }
            }
        }
        return productPromotionMap;
    }

    @Override
    public Map<Long, Boolean> matchPromotion(Long promotionId, Set<Long> productIdSet) {
        if(promotionId==null || productIdSet==null || productIdSet.size()==0){
            return Collections.emptyMap();
        }
        Map<Long,Boolean> matchMap = new HashMap<Long,Boolean>();
        for(Long productId:productIdSet){
            matchMap.put(productId,false);
            String key = PromotionConstant.PRODUCT_PROMOTION_RELATION_PREFIX + productId;
            Set<Object> promotionIdSet = redisRepository.getRedisTemplate().opsForZSet().range(key,0,-1);
            Set<Long> promotionIdLongSet = new HashSet<Long>();
            if(promotionIdSet!=null && promotionIdSet.size()>0){
                for(Object proIdObj:promotionIdSet){
                    promotionIdLongSet.add(Long.valueOf(proIdObj.toString()));
                }
            }
            if(promotionIdLongSet.contains(promotionId)){
                matchMap.put(productId,true);
            }
        }

        return matchMap;
    }
}
